﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Threading.Tasks;
using System.Threading;
using System.Windows;
using WPFcontrols =System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Forms;
using CractalLibrary;
using WPFMBOX = System.Windows.MessageBox;
using System.Runtime.Serialization;
using System.Numerics;


namespace GenerateDictionary
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public Configuration Config;
        private List<char[]> starts = new List<char[]>();
        private List<char[]> finishes = new List<char[]>();
        public static string tempfilenamestub = "TempCodegenPart";
        public static string ext = "txt";
        public List<string> FinalErrorReport = new List<string>();
        BigInteger totalsizeoffFilesinbytes = new BigInteger();
        BigInteger bytesprocessedthisfar = new BigInteger();

        public delegate void aVoidDelegate();
        public delegate void withparamdelegate(string item);
        public delegate void withojectparamdelegate(object item);
        private System.Windows.Threading.DispatcherTimer timer;

        public List<string> paddingvalues = new List<string>();
        private bool threadtasksfullyintanciated;
        private int FrequecyDiskCheck;
        
        public int bufferupdate;
        public PerformanceCount performancecounter;
        public object stacklock;
        public Stack<string> LastValueStack;

        public int numberofProcessors;
        public int numberofCores;
        public int cpuUpdatefrequency;
        private bool updateTOTALpercentbarPerformance = false;

        private bool charsetcontrolhasuserchangedeventbound = true;


        private int configcheckfrequency = 0;


        

        

        public aVoidDelegate startdictionarycreation;
        public withparamdelegate updatelastvalue;

        //wanted to play with a dynamically added control
        public System.Windows.Controls.Slider numbofthredsSlider;

        public cractal utilitycractal;

        //encapsulates a CPU thread task
        //future enhancement will be the GPU equivalent ATI - NVIDIA cuda I expect
        //It will smash out millions then.
        public CodeGenThreadTaskCPU[] ThreadTasks;

        private Task FileMergeProcess;
        private System.Threading.CancellationToken CancelProcessing;
        private System.Threading.CancellationTokenSource tokensource;

        public MainWindow()
        {
            //valueset default
            
            AppDomain currentDomain = AppDomain.CurrentDomain;
            currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
            Config = new Configuration();
           
            //purely an object for thread locking
            stacklock = new object();
           
            //stack of sample codes generated
            FrequecyDiskCheck = 0;
            bufferupdate = 0;
            numberofProcessors = 0;
            startdictionarycreation = new aVoidDelegate(dictionarybuild);


            performancecounter = new PerformanceCount();
            cpuUpdatefrequency = 5;


            //updates last value generated in the gui and performs,
            //update processor utilisation
            threadtasksfullyintanciated = false;
            timer = new System.Windows.Threading.DispatcherTimer();
            timer.Interval = new TimeSpan(500000);
            timer.Tick += updatelable;

            tokensource = new System.Threading.CancellationTokenSource();
            CancelProcessing = tokensource.Token;


           // utilitycractal = new cractal();
            utilitycractal = new cractal(Config.charactureset.ToArray()); ; //not used for codegeneration but for utility methods
            InitializeComponent();
            SetupThreadSlider();

            SetupPerformanceCounter();
            SetupCharsetTab();
            SetupConcurrentProcessingTab();
            SetupCodegenLable(); //just a tooltip
            SetupRunningThreadslable();
            SetupDiskspacelable();
            timer.Start();
        }

        private void SetupDiskspacelable()
        {
            DiskSpaceLbl.Visibility = Visibility.Hidden;
        }

        private void SetupRunningThreadslable()
        {
            RunningThreadsLBL.Content = "List of Running Threads - (NO CODE GENERATION THREADS RUNNING AT PRESENT)";
            
        }

        private void SetupCodegenLable()
        {
            string toolt  = "Only a Sample is shown, this is done so the processing threads are not restricted";
            toolt += "\r\n" + "to the user interface thread execution.";
            CodeLBL.ToolTip = toolt;
        }

        private void SetupConcurrentProcessingTab()
        {
            ConcurrentProcLBL.Content = "Thread Tasks Divided as Below:   <-- for code lengths of: ( "+ Config.MinCodeSize.ToString() + " - " + Config.MaxCodeSize.ToString() + " ) -->";

            NumberofThreadsLBL.Content = "Number of Concurrent Threads: " + (Config.NumberofThreadsSelected).ToString();
            NumberofThreadsLBL_Copy.Content = NumberofThreadsLBL.Content;

            if (((string)MaxWordSizeLBL.Content).Contains("Set the Maximum Code Length: ("))
            {
                calculateCodeGenDivisions();

                for (int x = 0; x < starts.Count(); x++)
                {
                    if (x == 0)
                    {
                        ThreadtasksTBOX.Text = "";
                    }
                    ThreadtasksTBOX.Text += ThreadHeaderText(x);
                    ThreadtasksTBOX.Text += "<-- start and finish values relate to the code gen engine only -->\r\n";
                }


            }
            else
            {
                ThreadtasksTBOX.Text = "You have set the size of the maximum size of the code you are looking to generate first, before I can show you the Thread Task Code Divisions";
            }
        }

        private void SetupCharsetTab()
        {
            MaxWordSizeLBL.Content = "Set the Maximum Code Length: ( " + Config.MaxCodeSize.ToString() + " )";
            MinWordSizeLBL.Content = "Set Minimum Code generation Length: ( " + Config.MinCodeSize.ToString() + " )";
            SetThreadNumberContraints();
            SetBufferContraints();
            if (charsetcontrolhasuserchangedeventbound)
            {
                CharsetpickerControl.OnUserChanged += UserModified;
                charsetcontrolhasuserchangedeventbound = false;
            }
        }

        private void UserModified(object sender, CharactureSetControlUserChangedEventArgs e)
        {
            CustomCharsetRadio.IsChecked = true;
        }

        private void SetBufferContraints()
        {
                       
            LastValueStack = new Stack<string>(500);
        }

        private void SetupThreadSlider()
        {
            numbofthredsSlider = new WPFcontrols.Slider();
            numbofthredsSlider.IsEnabled = true;
            numbofthredsSlider.SmallChange = 1;
            numbofthredsSlider.Maximum = 99;
            numbofthredsSlider.Value = 1;
            numbofthredsSlider.Minimum = 1;
            numbofthredsSlider.LargeChange = 1;
            this.numbofthredsSlider.ValueChanged += new System.Windows.RoutedPropertyChangedEventHandler<double>(this.updatethreadvalue);
            var a = new WPFcontrols.StackPanel();
            a.Children.Add(this.numbofthredsSlider);
            settingsGPbox.Content = a;
        }

        private void updatePerformanceBars()
        {
            try
            {
                List<Dictionary<string, float>> sample = new List<Dictionary<string, float>>();
                var a = performancecounter.GetnextValues();


                var Totalvalue = a.Where(k => k.Key.ToLower() == ("_Total".ToLower()));
                var ProcessorCorsValue = a.Where(k => k.Key.Contains(',') && (!k.Key.Contains(",_Total")));
                if (updateTOTALpercentbarPerformance)
                {
                    SetProgressBarValue("total", Totalvalue.ToList()[0].Value);
                }
                else
                {
                    updateTOTALpercentbarPerformance = true;
                }
                foreach (var item in ProcessorCorsValue)
                {
                    int proc = (int.Parse(item.Key.Remove(item.Key.IndexOf(',')))) + 1;
                    int core = int.Parse(item.Key.Remove(0, (1 + (item.Key.IndexOf(','))))) + 1;
                    SetProgressBarValue(proc.ToString() + "_Core" + core.ToString(), item.Value);

                }
            }
            catch (Exception e)
            {
                System.Windows.MessageBox.Show(e.Message);
            }

        }

        private void SetProgressBarValue(string p1, float p2)
        {
            foreach (var ctrl in ProcessorUsageStackPAN.Children)
            {
                if (ctrl is WPFcontrols.ProgressBar)
                {
                    if (((WPFcontrols.ProgressBar)ctrl).Name.ToLower().Contains(p1.ToLower()))
                    {
                        if (((WPFcontrols.ProgressBar)ctrl).Dispatcher.CheckAccess())
                        {
                            ((WPFcontrols.ProgressBar)ctrl).Value = (int)p2;
                        }
                        else
                        {
                            ((WPFcontrols.ProgressBar)ctrl).Dispatcher.BeginInvoke(new Action(() => ((WPFcontrols.ProgressBar)ctrl).Value = (int)p2));
                        }
                    }
                }

            }

        }

        private void SetupPerformanceCounter()
        {

            ProcessorUsageStackPAN.Visibility = System.Windows.Visibility.Visible;
            ProcessorUsageStackPAN.BringIntoView();
            var a = performancecounter.GetnextValues();

            var res = a.Where(k => k.Key.Contains(',') && (!k.Key.Contains(",_Total"))).Select(x => x.Key);
            numberofProcessors = 0;
            var listofprocessors = new List<string>();
            foreach (string item in res)
            {
                string proccessor = ((int.Parse(item.Remove(item.IndexOf(',')))) + 1).ToString();
                if (!listofprocessors.Contains("Processor " + proccessor))
                {
                    listofprocessors.Add("Processor " + proccessor);
                    numberofProcessors++;
                }
            }
            var total = a.Where(k => k.Key.ToLower() == ("_Total".ToLower())).Select(x => x.Key);
            WPFcontrols.ProgressBar tot = new WPFcontrols.ProgressBar();
            tot.Minimum = 0;
            tot.Maximum = 100;
            tot.SmallChange = 1;
            tot.LargeChange = 1;
            tot.Value = 0;
            tot.ToolTip = "Total CPU workload %";
            tot.Name = "ProcessorProgressBarTOTAL";
            tot.Height = 20;
            tot.MouseEnter += publish_BarValue;
            tot.Foreground = new SolidColorBrush(Colors.Red);
            ProcessorUsageStackPAN.Children.Add(tot);



            int z = 0;
            foreach (string element in listofprocessors)
            {
                var coresforprocessor = a.Where(k => k.Key.Contains(z.ToString() + ",") && (!k.Key.Contains(z.ToString() + ",_Total"))).Select(v => (v.Key.Remove(0, 1 + v.Key.IndexOf(','))));
                numberofCores = coresforprocessor.Count();
                foreach (var n in coresforprocessor)
                {
                    var c = int.Parse(n);
                    WPFcontrols.ProgressBar p = new WPFcontrols.ProgressBar();
                    p.Minimum = 0;
                    p.Maximum = 100;
                    p.SmallChange = 1;
                    p.LargeChange = 1;
                    p.Value = 0;
                    p.ToolTip = "Processor " + (z + 1).ToString() + " Core " + (c + 1).ToString() + " workload %";
                    p.Name = "ProcessorProgressBar_Proc" + (z + 1).ToString() + "_Core" + (c + 1).ToString();
                    p.Height = 20;
                    p.MouseEnter += publish_BarValue;
                    ProcessorUsageStackPAN.Children.Add(p); //Percentageforprocess

                }

                z++;
            }


            INFOprocessorTbox.Text = "Current System has physical Processors: " + numberofProcessors.ToString();
            INFOprocessorTbox.Text += "\r\nEach Processor consists of Cores: " + numberofCores.ToString() + "\r\n";
            INFOprocessorTbox.Text += "\r\nGiving you a total of " + (numberofCores * numberofProcessors).ToString() + " cores for simulataneous computation";
            INFOprocessorTbox.Text += "\r\n\r\nThe below bar graphs are indicating processor utilisation for all processing cores, \r\nhover your cursor over a bar to see what it relates to.";


        }

        private void publish_BarValue(object sender, System.Windows.Input.MouseEventArgs e)
        {
            var v = (sender as WPFcontrols.ProgressBar).Value;
            Percentageforprocess.Dispatcher.BeginInvoke(new Action(() => Percentageforprocess.Content = "PERCENTAGE UTILISATION: " + ((int)v).ToString() + "%"));
        }

        private void updatelable(object sender, EventArgs e)
        {

            if (threadtasksfullyintanciated)
            {
                if (FrequecyDiskCheck == 0)
                {
                    performdiskspacecheck();
                    FrequecyDiskCheck = 5;
                }
                else
                {
                    FrequecyDiskCheck--;
                }

                if (cpuUpdatefrequency == 0)
                {
                    updatePerformanceBars();
                    refreshrunningThreads();
                    cpuUpdatefrequency = 2; //update cpu performance every two timer ticks
                }
                else
                {
                    cpuUpdatefrequency--;
                }

                if (LastValueStack.Count > 0)
                {
                    var a = LastValueStack.Pop();
                    a = a + "\r\nCode Sample Buffer Level: " + LastValueStack.Count().ToString();
                    updatecount(a);


                }
            }
            else
            {
                if (configcheckfrequency == 0)
                {
                    if (FilelocationsTabMENU.IsSelected || FileLocationTab.IsSelected)
                    {//tempfile location tab is the active tab
                    CyclicCheckThreadTempfiles();
                    }

                    configcheckfrequency = 5;
                }
                else
                {
                    configcheckfrequency--;
                }

            }

        }

        private void CyclicCheckThreadTempfiles()
        {
            if(TempThreadListBox.Items.Count > 0){
                int x = 0;
                foreach (bool isvalid in Config.testConfigfilepaths())
                {
                    if ((x - 1) >= TempThreadListBox.Items.Count)
                    {
                        break;
                    }
                    if (x == 0)
                    {
                        if (!isvalid)
                        {
                            var content = (string)MainFileLocationLBL.Content;
                            content += (!content.Contains(Utility.Utility.FilelocationstabINVALIDfilepath)) ? Utility.Utility.FilelocationstabINVALIDfilepath : "";
                            MainFileLocationLBL.Content = content;
                            MainFileLocationLBL.Foreground = new SolidColorBrush(Colors.Red);
                        }
                        else
                        {
                            var content = (string)MainFileLocationLBL.Content;
                            content = content.Replace(Utility.Utility.FilelocationstabINVALIDfilepath, "");
                            MainFileLocationLBL.Content = content;
                            MainFileLocationLBL.Foreground = new SolidColorBrush(Colors.Green);

                        }
                    }
                    else
                    {
                        Color notificicaitonCOL = new Color();
                        if (isvalid)
                        {
                            notificicaitonCOL = Colors.Green;
                        }
                        else
                        {
                            notificicaitonCOL = Colors.Red;
                        }

                        (TempThreadListBox.Items[x - 1] as WPFcontrols.Label).Foreground = new SolidColorBrush(notificicaitonCOL);

                    }
                    x++;   
                }
            }
        }

        private void performdiskspacecheck()
        {
            DiskSpaceLbl.Visibility = System.Windows.Visibility.Visible;
            KeyValuePair<string, long> minsizedrive = new KeyValuePair<string, long>("not assined", -1);
            List<string> uniqueDrives = new List<string>();
            uniqueDrives.AddRange(ThreadTasks.Where(v => Utility.Utility.GetThreadContextMenuetext(v.ConfigCodeHeader, v.notification, ThreadState(v)) == "Shut Down Code Generation Process" && Directory.Exists((System.IO.Path.GetPathRoot(v.Filepath)))).Select(x => (System.IO.Path.GetPathRoot(x.Filepath))).Distinct().ToList());
            if (uniqueDrives.Count > 0)
            {
                foreach (string drive in uniqueDrives)
                {
                    var drvinfo = new DriveInfo(drive);
                    if (minsizedrive.Value == -1)
                    {
                        minsizedrive = new KeyValuePair<string, long>(drive, drvinfo.TotalFreeSpace);
                    }
                    else
                    {
                        if (drvinfo.TotalFreeSpace < minsizedrive.Value)
                        {
                            minsizedrive = new KeyValuePair<string, long>(drive, drvinfo.TotalFreeSpace);
                        }

                    }
                }

                int freespaceMB = (int)((minsizedrive.Value / (long)1024) / (long)1024);
                var tootip = "";
                if (freespaceMB > 1000)
                {


                    DiskSpaceLbl.Background = new SolidColorBrush(Color.FromRgb(179, 236, 139));
                    DiskSpaceLbl.Content = "Disk Space: ok > 1gb";
                    tootip = "Drive utilised by code generation with smallest volume: " + minsizedrive.Key + "\r\n";
                    tootip += "Volume currently sits at: " + freespaceMB.ToString() + "MB of available freespace";
                    DiskSpaceLbl.ToolTip = tootip;
                }
                else if (freespaceMB < 1000 && freespaceMB > 500)
                {


                    DiskSpaceLbl.Background = new SolidColorBrush(Color.FromRgb(229, 236, 88));
                    DiskSpaceLbl.Content = "Disk Space: low  Between 1gb and 500mb";
                    tootip = "Drive utilised by code generation with smallest volume: " + minsizedrive.Key + "\r\n";
                    tootip += "Volume currently sits at: " + freespaceMB.ToString() + "MB of available freespace";
                    DiskSpaceLbl.ToolTip = tootip;
                }
                else if (freespaceMB < 500 && freespaceMB > 200)
                {
                    DiskSpaceLbl.Background = new SolidColorBrush(Color.FromRgb(229, 236, 88));
                    DiskSpaceLbl.Content = "Disk Space: critical < 500mb (automtic shutdown of code gen will occure at 200mb free)";
                    tootip = "Drive utilised by code generation with smallest volume: " + minsizedrive.Key + "\r\n";
                    tootip += "Volume currently sits at: " + freespaceMB.ToString() + "MB of available freespace";
                    DiskSpaceLbl.ToolTip = tootip;
                }
                else if (freespaceMB <= 200)
                {
                    for (int x = 0; x < ThreadTasks.Count(); x++)
                    {
                        if (System.IO.Path.GetPathRoot(ThreadTasks[x].Filepath) == minsizedrive.Key)
                        {
                            ThreadTasks[x].DiskspaceshutdownThread();
                        }
                    }
                    System.Windows.MessageBox.Show("All code generation threads on volumes afected by lack of disk space have been requested to shut down");
                }
            }
           
        }

        private void refreshrunningThreads()
        {
            int ThreadsRunning = 0;
            var listofThreaditems = new List<WPFcontrols.Label>();
            foreach (CodeGenThreadTaskCPU a in ThreadTasks)
            {
                string listitem = a.ConfigCodeHeader;
                var threadlble = new WPFcontrols.Label();
                var threads = ThreadState(a);
                threadlble.Content = Utility.Utility.GetThreadListContent(a.ConfigCodeHeader, a.notification, ThreadState(a));// ((listitem.Remove(listitem.IndexOf('\r'))) + " Current State: " + (threads == System.Threading.Tasks.TaskStatus.Running.ToString() ? (a.notification.Any() ? "The thread is scheduled for shutdown" : "Currently Running") : (threads == System.Threading.Tasks.TaskStatus.RanToCompletion.ToString() ? "Thread has terminated due to: (" + (a.notification.Any() ? a.notification.FirstOrDefault() + ")" : "currently uknown reason" + ")") : ThreadState(a))));
                threadlble.ToolTip = a.ConfigCodeHeader;
                listofThreaditems.Add(threadlble);

                var listofmenuitems = new List<WPFcontrols.MenuItem>();
                var m1 = new WPFcontrols.MenuItem();


                string menueoption = (threads == System.Threading.Tasks.TaskStatus.Running.ToString() ||threads == System.Threading.Tasks.TaskStatus.WaitingToRun.ToString())  ? (a.notification.Any() ? "The thread is scheduled for shutdown" : "Shut Down Thread") : (threads == System.Threading.Tasks.TaskStatus.RanToCompletion.ToString() ? "Thread has terminated due to: (" + (a.notification.Any() ? a.notification.FirstOrDefault() + ")" : "currently uknown reason" + ")") : ThreadState(a));
               
                switch(threads){
                    case "Running" :
                        ThreadsRunning++;
                        break;
                    case "WaitingToRun":
                        ThreadsRunning++;
                        break;
                    default:
                        break;
                    
                }
                m1.Header = Utility.Utility.GetThreadContextMenuetext(a.ConfigCodeHeader, a.notification, ThreadState(a));
                m1.CommandParameter = (string)threadlble.Content;
                m1.Click += threadcontextmenueclicked;
                threadlble.ContextMenu = new WPFcontrols.ContextMenu();
                threadlble.ContextMenu.Items.Add(m1);
            }
            if (listofThreaditems.Count != RunningThreadsExecutionListBox.Items.Count)
            {
                RunningThreadsExecutionListBox.Items.Clear();
                foreach (WPFcontrols.Label lbl in listofThreaditems)
                {
                    RunningThreadsExecutionListBox.Items.Add(lbl);
                }

            }
            else
            {
                bool different = false;
                for (int x = 0; x < listofThreaditems.Count; x++)
                {
                    if ((string)((WPFcontrols.Label)RunningThreadsExecutionListBox.Items[x]).Content != (string)listofThreaditems[x].Content)
                    {
                        different = true;
                        break;
                    }
                }
                if (different)
                {
                    RunningThreadsExecutionListBox.Items.Clear();
                    foreach (WPFcontrols.Label lbl in listofThreaditems)
                    {
                        RunningThreadsExecutionListBox.Items.Add(lbl);
                    }
                }

            }

            if (ThreadsRunning == 0)
            {
                timer.Stop();
                FinishProcess();
                

            }

        }

        private void FinishProcess()
        {
            
           // System.Windows.MessageBox.Show("Code Generation Process has finished");
            RunningThreadsLBL.Content = "List of Running Threads - (ALL CODE GENERATION THREADS HAVE TERMINATED EXECUTION)";
            threadtasksfullyintanciated = false;
            LastValueStack.Clear();
            
            
            FinishButton.Content = "Cancel";
            ProcessCompleteLBL.Visibility = Visibility.Hidden;
            RunningThreadsLBL.Visibility = System.Windows.Visibility.Hidden;
            RunningThreadsExecutionListBox.Visibility = System.Windows.Visibility.Hidden;
            FinishprocessCanvas.Visibility = System.Windows.Visibility.Visible;
            FinishprocessCanvas.BringIntoView();
            codefilelocationLBL.Content = "Your code file is been compiled at your chosen location:\r\n[ " + Config.Filepath + " ]";
            FinishProcessCompleteBAR.Value = 0.0;
            FinishProcessCompleteBAR_tempfile.Value = 0.0;
            
            GC.Collect();
            FileMergeProcess = new Task(new Action(InitiateFileMerge), tokensource.Token); ;
            FileMergeProcess.Start();

            
            
            
            
        }

        private void InitiateFileMerge()
        {
            int numberofFilestoProcess = ThreadTasks.Count();
            List<bool> fileExists = new List<bool>();

            foreach (var file in ThreadTasks.Select(x => x.Filepath))
            {
                if (File.Exists(file))
                {
                    fileExists.Add(true);
                }
                else
                {
                    fileExists.Add(false);
                }
            }

            List<string> validExistingCodegenTempFiles = new List<string>();
            int z = 0;
            foreach (bool fileisthere in fileExists)
            {
                if (fileisthere)
                {
                    validExistingCodegenTempFiles.Add(ThreadTasks[z].Filepath);
                }
                else
                {
                    FinalErrorReport.Add("Missing codegen Temp file detected: [ " + ThreadTasks[z].Filepath +" ]");

                }
                z++;
            }

            
            totalsizeoffFilesinbytes = 0;
            foreach (var f in validExistingCodegenTempFiles)
            {
                try
                {
                    var finfo = new FileInfo(f);
                    totalsizeoffFilesinbytes = totalsizeoffFilesinbytes + finfo.Length;
                }
                catch { 
                FinalErrorReport.Add("An error occured with tyring to read my temp code gen files: [ "+f+" ]");
                }
            }

            
            bytesprocessedthisfar = 0;
            foreach (var tempfile in validExistingCodegenTempFiles)
            {
                CompileFinalFile(tempfile, totalsizeoffFilesinbytes);
                if (Config.cleanuptempfiles)
                {
                    File.Delete(tempfile);
                }
                if (CancelProcessing.IsCancellationRequested)
                {
                    break;
                }
            }

            if (CancelProcessing.IsCancellationRequested)
            {
                WPFMBOX.Show("The Codegen file compiling has been halted.");
                if (FinishButton.Dispatcher.CheckAccess())
                {
                    FinishButton.Dispatcher.BeginInvoke(new Action(() => FinishButton.Content = "Close"));

                }
                else
                {
                    FinishButton.Content = "Close";
                }
                
                    ProcessCompleteLBL.Dispatcher.BeginInvoke(new Action(() => ProcessCompleteLBL.Content = "Codegen File compiling cancelled by user.\r\nProcess complete"));
                    ProcessCompleteLBL.Dispatcher.BeginInvoke(new Action(() => ProcessCompleteLBL.Visibility = System.Windows.Visibility.Visible));
                    PercentCodeFileCompleteLBL.Dispatcher.BeginInvoke(new Action(() => PercentCodeFileCompleteLBL.Visibility = System.Windows.Visibility.Hidden));
                    FinishProcessCompleteBAR.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR.Visibility = System.Windows.Visibility.Hidden));
                    FinishProcessCompleteBAR_tempfile.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR_tempfile.Visibility = System.Windows.Visibility.Hidden));
                    codefilelocationLBL.Dispatcher.BeginInvoke(new Action(() => codefilelocationLBL.Visibility = System.Windows.Visibility.Hidden));
                    tempfileprocessedLBL.Dispatcher.BeginInvoke(new Action(() => tempfileprocessedLBL.Visibility = System.Windows.Visibility.Hidden));
            }
            else
            {
                FinishProcessCompleteBAR.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR.Value = 100.00));

                
                FinishProcessCompleteBAR_tempfile.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR_tempfile.Value = 100.00));
              
                WPFMBOX.Show("The Codegen file compiling has Completed.");
                
                    FinishButton.Dispatcher.BeginInvoke(new Action(() => FinishButton.Content = "Close"));
                    PercentCodeFileCompleteLBL.Dispatcher.BeginInvoke(new Action(() => PercentCodeFileCompleteLBL.Visibility = System.Windows.Visibility.Hidden));
                    FinishProcessCompleteBAR.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR.Visibility = System.Windows.Visibility.Hidden));
                    FinishProcessCompleteBAR_tempfile.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR_tempfile.Visibility = System.Windows.Visibility.Hidden));
                    codefilelocationLBL.Dispatcher.BeginInvoke(new Action(() => codefilelocationLBL.Visibility = System.Windows.Visibility.Hidden));
                    tempfileprocessedLBL.Dispatcher.BeginInvoke(new Action(() => tempfileprocessedLBL.Visibility = System.Windows.Visibility.Hidden));

                   // ProcessCompleteLBL.Dispatcher.BeginInvoke(new Action(() => ProcessCompleteLBL.Content = "Codegen File compiling cancelled by user.\r\nProcess complete"));
                    ProcessCompleteLBL.Dispatcher.BeginInvoke(new Action(() => ProcessCompleteLBL.Visibility = System.Windows.Visibility.Visible));
                    




            }
            
        }

        private void CompileFinalFile(string tempfile, BigInteger totalsizeoffFilesinbytes)
        {
            byte[] buffer = new byte[4096]; // buffer with 4 kB dimension
            var Finf = new FileInfo(tempfile);
            BigInteger sizeoftempfile = Finf.Length;
            BigInteger tempfilebytesreadthisfar = 0;
            tempfileprocessedLBL.Dispatcher.BeginInvoke(new Action(() => tempfileprocessedLBL.Content ="Percentage Temp File Currently processed: [" + tempfile+"]"));
            Stream streamin = File.Open(tempfile, FileMode.Open);
            Stream outstream = File.Open(Config.Filepath, FileMode.Append);
            bool everysecond = false;
            int read = 0;
            do
            {
                if (CancelProcessing.IsCancellationRequested)
                {
                    break;
                }

                if (everysecond)
                {
                    int newpercent = (int)(100.00 * ((double)bytesprocessedthisfar / (double)totalsizeoffFilesinbytes));

                    FinishProcessCompleteBAR.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR.Value = newpercent));

                    int filepercent = (int)(100.00 * ((double)tempfilebytesreadthisfar / (double)sizeoftempfile));
                    FinishProcessCompleteBAR_tempfile.Dispatcher.BeginInvoke(new Action(() => FinishProcessCompleteBAR_tempfile.Value = filepercent));
                }
                everysecond = everysecond ? false : true;   
              
                // read partial content of net (asynchronously)
                read = streamin.Read(buffer, 0, buffer.Length);

                outstream.Write(buffer, 0, read);

                tempfilebytesreadthisfar += read;
                bytesprocessedthisfar += read;

            }
            while (read > 0);

            streamin.Close();
            streamin.Dispose();
            outstream.Close();
            outstream.Dispose();

        }

        private void FinishProcessA(){
            
            seetingsTabMenu.IsEnabled = true;
            SelectorButton.IsEnabled = true;
            RunningThreadsLBL.Visibility = System.Windows.Visibility.Visible;
            RunningThreadsExecutionListBox.Visibility = System.Windows.Visibility.Visible;

            ProcessCompleteLBL.Visibility = System.Windows.Visibility.Hidden;
            ProcessCompleteLBL.Content = "Congratulations Process\r\nComplete.";
            PercentCodeFileCompleteLBL.Visibility = System.Windows.Visibility.Visible;
            FinishProcessCompleteBAR.Visibility = System.Windows.Visibility.Visible;
            FinishProcessCompleteBAR_tempfile.Visibility = System.Windows.Visibility.Visible;
            codefilelocationLBL.Visibility = System.Windows.Visibility.Visible;
            tempfileprocessedLBL.Visibility = System.Windows.Visibility.Visible;

            timer.Start();

        }

        private void threadcontextmenueclicked(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            var mitem = (sender as WPFcontrols.MenuItem);
            if ((string)mitem.Header == "Shut Down Code Generation Process")
            {

                var commandparam = ((string)mitem.CommandParameter).Remove(((string)mitem.CommandParameter).IndexOf('C') -1); //minus one means we get the white space
                for (int x = 0; x < ThreadTasks.Count(); x++)
                {
                    if (ThreadTasks[x].ConfigCodeHeader.Contains(commandparam+"\r"))
                    {
                        if (ThreadState(ThreadTasks[x]) == TaskStatus.Running.ToString() || ThreadState(ThreadTasks[x]) == TaskStatus.WaitingToRun.ToString())
                        {
                            ThreadTasks[x].ShutdownThread();
                        }
                    }

                }
            }
            else
            {
                var commandparam = ((string)mitem.CommandParameter).Remove(((string)mitem.CommandParameter).IndexOf('C') - 1); //minus one means we get the white space
                for (int x = 0; x < ThreadTasks.Count(); x++)
                {
                    if (ThreadTasks[x].ConfigCodeHeader.Contains(commandparam + "\r"))
                    {
                        System.Windows.MessageBox.Show(Utility.Utility.GetThreadListContent(ThreadTasks[x].ConfigCodeHeader,ThreadTasks[x].notification, ThreadState(ThreadTasks[x])));
                    }

                }
            }
        }

        private string ThreadState(CodeGenThreadTaskCPU a)
        {
            return a.ThreadState.ToString();
        }

        public void updatecount(string data)
        {
            if (CodeLBL.Dispatcher.CheckAccess()) //wpf equivalent of windows forms ctrl.invokerequired
            {

                CodeLBL.Content = "Code Generated Sample: " + data;

            }
            else
            {
                CodeLBL.Dispatcher.BeginInvoke(new Action(() => CodeLBL.Content = "Code Generated Sample: " + data));
            }
        }

        private void dictionarybuild()
        {
            //force a garbadge collection before getting heavy
            GC.Collect();
            for (int z = 1; z < Config.MaxCodeSize; z++)
            {
                string paditem = "";
                for (int pad = z; pad > 0; pad--)
                {
                    paditem += utilitycractal.MinUnitValue.ToString();

                }
                paddingvalues.Add(paditem);
            }
            
            int x = 0;
            foreach (var t in ThreadTasks)
            {

                ThreadTasks[x] = new CodeGenThreadTaskCPU(Config.charactureset.ToArray());//Task(new Action(IncrementandStoreCracktal));
                ThreadTasks[x].Filepath = Config.ThreadTempFilepaths[x];
                ThreadTasks[x].MaxCodeSize = Config.MaxCodeSize;
                ThreadTasks[x].MinCodeSize = Config.MinCodeSize;
                ThreadTasks[x].PaddingValues(ref paddingvalues);
                ThreadTasks[x].SetStartValue = (char[])((starts[x]).Clone());
                ThreadTasks[x].SetEndValue = (char[])((finishes[x]).Clone());
                ThreadTasks[x].ConfigCodeHeader = ThreadHeaderText(x);
                ThreadTasks[x].OnBufferElementAdded += CodeGenTasks_BufferElementAdded;
                ThreadTasks[x].CodeGenStart();
                
                x++;
            }


            threadtasksfullyintanciated = true;

        }

        private void setupTempFilepaths()
        {
            SetupConcurrentProcessingTab();

            if (AutomaticTempFileConfig.IsChecked == null ? false : AutomaticTempFileConfig.IsChecked.Value)
            {
                setupAutoTempFilepaths();
            }
            else
            {
                setupCustomFilePaths();

            }
        }

        private void CodeGenTasks_BufferElementAdded(object sender, CodeGenThreadTaskCPU.RaiseBufferElmentAddeventArgs e)
        {

            lock (stacklock) //locking for updates of the stack
            {
                //updatecount(e.Latestvalue);
                if (bufferupdate == (Config.NumberofThreadsSelected * 30))
                {

                    if (LastValueStack.Count < 90000)
                    {

                        LastValueStack.Push(e.Latestvalue);

                    }

                    bufferupdate = 0;
                }
                else
                {
                    bufferupdate++;


                }
            }
        }


        private void calculateCodeGenDivisions()
        {
            var endvalue = new char[Config.MaxCodeSize];
            for (int i = 0; i < Config.MaxCodeSize; i++)
            {
                endvalue[i] = utilitycractal.MaxUnitValue;
            }
            var num = utilitycractal.RoughDivideBy(endvalue, Config.NumberofThreadsSelected);
            ThreadTasks = new CodeGenThreadTaskCPU[Config.NumberofThreadsSelected];
            starts.Clear();
            finishes.Clear();

            for (int k = 0; k < Config.NumberofThreadsSelected; k++)
            {
                if (k == 0)
                {
                    starts.Add(new char[] { utilitycractal.MinUnitValue });
                    finishes.Add(num);
                }
                else
                {
                    
                    utilitycractal.value = (char[])((finishes[k - 1]).Clone());
                    utilitycractal.increment();
                    starts.Add(utilitycractal.value);
                    if (finishes.Count() == (Config.NumberofThreadsSelected - 1))
                    {
                        finishes.Add(endvalue);
                    }
                    else
                    {
                        finishes.Add(utilitycractal.ADD((char[])((finishes[k - 1]).Clone()), (char[])num.Clone()).ToArray());
                    }

                }
            }

        }

        private void updatethreadvalue(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            int i = ((int)e.NewValue);
            if (Config.NumberofThreadsSelected != i)
            {
                Config.NumberofThreadsSelected = i;
                SetupConcurrentProcessingTab();
                SetupTempFileLocations();
            }

            
        }

        private void SetupTempFileLocations()
        {
            if (AutomaticTempFileConfig.IsChecked == null ? false : AutomaticTempFileConfig.IsChecked.Value)
            {
                setupAutoTempFilepaths();
            }
            else
            {
                setupCustomFilePaths();

            }
        }

        private string ThreadHeaderText(int x)
        {
            string Txt = "";
            Txt += "Thread ID: " + (x + 1).ToString() + "\r\n";
            var str = new String(starts[x]);
            Txt += "\tCodeGen Start (" + str + ")\r\n";
            str = new String(finishes[x]);
            Txt += "\tCodeGen Finish (" + str + ")\r\n\r\n";
            return Txt;
        }

        private void SetFilenameAndpath(object sender, RoutedEventArgs e)
        {
            var sfd = new Microsoft.Win32.SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = ext;
            sfd.Filter = Utility.Utility.CodegenSFDfilter;
            sfd.FilterIndex = 1;
            bool? resultofdialog = sfd.ShowDialog();
            if (resultofdialog.HasValue ? resultofdialog.Value : false)
            {



                Config.Filepath = sfd.FileName;
                var Finfo = new FileInfo(Config.Filepath);

                if (System.IO.Path.GetPathRoot(Config.Filepath) == Finfo.DirectoryName)
                {
                    Config.dirpath = Finfo.DirectoryName.Replace("\\", "");
                    
                }
                else
                {
                    Config.dirpath = Finfo.DirectoryName;
                }
                if (!string.IsNullOrEmpty(Config.Filepath))
                {
                    MainFileLocationLBL.Content = "FILE PATH SET: " + Config.Filepath;
                    if (AutomaticTempFileConfig.IsChecked == null ? false : AutomaticTempFileConfig.IsChecked.Value)
                    {
                        setupAutoTempFilepaths();
                    }
                    else
                    {
                        setupCustomFilePaths();

                    }

                }
                else
                {
                    MainFileLocationLBL.Content = "A file Location has not been set!";

                }



            }
            else
            {

            }

        }
        private void setupCustomFilePaths()
        {
            if (!string.IsNullOrEmpty(Config.Filepath))
            {
                Disabled_FunctionalityLBL.Visibility = System.Windows.Visibility.Hidden;
                if (Config.ThreadTempFilepaths.Count == 0)
                {
                    setupAutoTempFilepaths();

                }
                else
                {
                    if (Config.NumberofThreadsSelected > Config.ThreadTempFilepaths.Count())
                    {

                        int x = Config.ThreadTempFilepaths.Count();
                        while (x <= Config.NumberofThreadsSelected)
                        {
                            Config.ThreadTempFilepaths.Add(Config.dirpath + @"\" + tempfilenamestub + "-" + x.ToString() + "." + ext);
                            x++;
                        }


                    }

                }
                //TempThreadListBox
                TempThreadListBox.Items.Clear();
                for (int l = 0; l < Config.NumberofThreadsSelected; l++)
                {
                    WPFcontrols.Label v = new WPFcontrols.Label();
                    v.Content = Config.ThreadTempFilepaths[l];
                    TempThreadListBox.Items.Add(v);

                }
            }
            else
            {
                TempThreadListBox.Items.Clear();
                Disabled_FunctionalityLBL.Visibility = System.Windows.Visibility.Visible;
            }
            setTempfileselectCount(TempThreadListBox.SelectedItems.Count);
        }

        private void setupAutoTempFilepaths()
        {
            if (!string.IsNullOrEmpty(Config.Filepath))
            {
                Disabled_FunctionalityLBL.Visibility = System.Windows.Visibility.Hidden;
                Config.ThreadTempFilepaths.Clear();
                int x = 0;
                while (x < Config.NumberofThreadsSelected)
                {
                    Config.ThreadTempFilepaths.Add(Config.dirpath + @"\" + tempfilenamestub + "-" + x.ToString() + "." + ext);
                    x++;
                }
                TempThreadListBox.Items.Clear();
                for (int l = 0; l < Config.NumberofThreadsSelected; l++)
                {

                    WPFcontrols.Label v = new WPFcontrols.Label();
                    v.Content = Config.ThreadTempFilepaths[l];
                    TempThreadListBox.Items.Add(v);

                }

            }
            else
            {
                Disabled_FunctionalityLBL.Visibility = System.Windows.Visibility.Visible;
            }
            setTempfileselectCount(TempThreadListBox.SelectedItems.Count);
        }

        private void ApplyCharactureSettings(object sender, RoutedEventArgs e)
        {
            try
            {
                if (MaxSizeTBOX.Text.Trim() == "")
                {
                    MaxSizeTBOX.Text = Config.MaxCodeSize.ToString();
                }

                if (MinimumCodeSizeTBOX.Text.Trim() == "")
                {
                    MinimumCodeSizeTBOX.Text = Config.MinCodeSize.ToString();
                }

                Config.MaxCodeSize = int.Parse(MaxSizeTBOX.Text.Trim());
                Config.MinCodeSize = int.Parse(MinimumCodeSizeTBOX.Text.Trim());



                if (!(Config.MaxCodeSize < 1))
                {
                    if (Config.MaxCodeSize > 5000)
                    {
                        System.Windows.MessageBox.Show("The absoloute maximum word size for code generation is 5000 charactures");
                        MaxSizeTBOX.Text = "5000";
                    }
                    else
                    {
                        TestMinCodesize();
                        
                        

                        
                    }

                }
                else
                {
                    System.Windows.MessageBox.Show("Mate come on enter a integer greater than 0");
                    MaxSizeTBOX.Text = "";
                }
            }
            catch
            {
                System.Windows.MessageBox.Show("You have to enter a number not letters or weird charactures.");
                MaxSizeTBOX.Text = "";
            }
        }

        private void TestMinCodesize()
        {
            //Setcodegencharacturesets();
            //SetupCharsetTab();
            if (!(Config.MinCodeSize < 1))
            {
                if (Config.MinCodeSize > 5000)
                {
                    System.Windows.MessageBox.Show("The Maximum word size for code generation is 5000 charactures, so the minimum specified definitely needs adjusting.");
                    MinimumCodeSizeTBOX.Text = "1";
                }
                else
                {
                    if (Config.MaxCodeSize >= Config.MinCodeSize)
                    {
                        
                        Setcodegencharacturesets();
                        SetupCharsetTab();
                        System.Windows.MessageBox.Show("Settings Applied");
                    }
                    else
                    {
                        System.Windows.MessageBox.Show("The minimum size for code generation has been set higher than the maximum size for code generation.  See a problem with this?");
                        MinimumCodeSizeTBOX.Text = "1";
                        MaxSizeTBOX.Text = "1";
                        Config.MaxCodeSize = 1;
                        Config.MinCodeSize = 1;

                    }
                }

            }
            else
            {
                System.Windows.MessageBox.Show("Mate come on enter a integer greater than 0 (I'm looking at the minimum code size");
                MinimumCodeSizeTBOX.Text = "";
            }
        }

        private void Setcodegencharacturesets()
        {
            if (CharsetpickerControl.getSelectedcharset().Count() < 2)
            {
                System.Windows.MessageBox.Show("I can't apply your characture set, there needs to be at least two charactures selected. \r\nI will default back to previous characture set.");
                CharsetpickerControl.setselectedchars(Config.charactureset);
            }
            else
            {
                Config.charactureset.Clear();
                Config.charactureset.AddRange(CharsetpickerControl.getSelectedcharset());
                Config.isStandardcharset = StandardCharsetRadio.IsChecked.HasValue ? StandardCharsetRadio.IsChecked.Value : false;
                if (Config.isStandardcharset)
                {
                    Config.StandardCharsetincludes[0] = CHKNUMS.IsChecked.HasValue ? CHKNUMS.IsChecked.Value : false;
                    Config.StandardCharsetincludes[1] = CHKUPPER.IsChecked.HasValue ? CHKUPPER.IsChecked.Value : false;
                    Config.StandardCharsetincludes[2] = CHKLOWER.IsChecked.HasValue ? CHKLOWER.IsChecked.Value : false;
                }
                utilitycractal = new cractal(Config.charactureset.ToArray());
            }

        }

        private void SetThreadNumberContraints()
        {
           numbofthredsSlider.Maximum = utilitycractal.GetMaxNumberOfThreads(ref Config.MaxCodeSize);
        }

        private void LaunchValidation(object sender, RoutedEventArgs e)
        {
            setupTempFilepaths();
            List<string> errors = new List<string>();
            if (Validate(ref errors))
            {
                calculateCodeGenDivisions();
                startdictionarycreation.BeginInvoke(null, null);
                

                ConfigErrorsStackPannel.Children.Clear();
                ConfigErrorsStackPannel.Visibility = System.Windows.Visibility.Hidden;
                ErrorInSetupLBL.Visibility = System.Windows.Visibility.Hidden;
                RunningThreadsExecutionListBox.Visibility = System.Windows.Visibility.Visible;
                RunningThreadsLBL.Visibility = System.Windows.Visibility.Visible;
                SelectorButton.IsEnabled = false;
                seetingsTabMenu.IsEnabled = false;
                RunningThreadsLBL.Content = "List of Running Threads - right click for options.";
                
                
                


            }
            else
            {
                RunningThreadsExecutionListBox.Visibility = System.Windows.Visibility.Hidden;
                RunningThreadsLBL.Visibility = System.Windows.Visibility.Hidden;
                ConfigErrorsStackPannel.Children.Clear();
                ConfigErrorsStackPannel.Visibility = System.Windows.Visibility.Visible;
                ErrorInSetupLBL.Visibility = System.Windows.Visibility.Visible;
                foreach (var s in errors)
                {
                    var l = new WPFcontrols.Label();
                    l.Content = s;
                    l.Foreground = new SolidColorBrush(Colors.Red);

                    ConfigErrorsStackPannel.Children.Add(l);


                }

            }
        }

        private bool Validate(ref List<string> errors)
        {
            bool errorfree = true;
            errors.Clear();
            if (string.IsNullOrEmpty(Config.Filepath))
            {
                errors.Add("Need to set a file path: (located in settings under file location tab)");
                errorfree = false;
            }


            var filelist = "";
            List<string> filecollisions = new List<string>();
            foreach (var path in Config.ThreadTempFilepaths)
            {
                if (Config.Filepath == path)
                {
                    filecollisions.Add(path);
                }

            }
            if (filecollisions.Count > 0)
            {
                bool everytwo = false;
                foreach (var f in filecollisions.Select(x => x + (everytwo ? "\r\n" : "\t")))
                {
                    filelist += f;
                    everytwo = (everytwo ? false : true);
                }
                var a = System.Windows.MessageBox.Show("You have chosen a completion file name that will conflict with the\r\ncode generator temp files, the affected temp file list below:\r\n\r\n" + filelist + "\r\n\r\nDo you want me to append a characture to the file name for uniqueness?", "Append Characture?", MessageBoxButton.OKCancel);
                if (a == MessageBoxResult.OK)
                {
                    int x = 0;
                    while (Config.ThreadTempFilepaths.Contains(Config.Filepath))
                    {
                        var fnamewithoutextention = "";
                        if (x == 0)
                        {
                            fnamewithoutextention = System.IO.Path.GetFileNameWithoutExtension(Config.Filepath);
                        }
                        else
                        {
                            fnamewithoutextention = (System.IO.Path.GetFileNameWithoutExtension(Config.Filepath)).Replace("-" + (x - 1).ToString(),"");
                        }
                        var dir = System.IO.Path.GetDirectoryName(Config.Filepath);
                        var extention = System.IO.Path.GetExtension(Config.Filepath);
                        Config.Filepath = dir + "\\" + fnamewithoutextention + "-" + x.ToString() + "." + extention;
                        x++;


                    }
                    MainFileLocationLBL.Content = "FILE PATH SET: " + Config.Filepath;
                    if (AutomaticTempFileConfig.IsChecked == null ? false : AutomaticTempFileConfig.IsChecked.Value)
                    {
                        setupAutoTempFilepaths();
                    }
                    else
                    {
                        setupCustomFilePaths();

                    }
                    
                    
                }
                else
                {
                    errors.Add("The code generation would have faulted in the final steps due to your selected file path for ");
                    errors.Add("the end output file.");
                    errors.Add("Please change the filename in settings --> file locations tab");
                    errors.Add("");
                    errorfree = false;
                    return errorfree;
                }


            }


            if (!String.IsNullOrEmpty(Config.Filepath))
            {
                int z = 0;
                foreach (bool validpath in Config.testConfigfilepaths())
                {


                    if (!validpath)
                    {
                        if (z == 0)
                        {
                            errors.Add("The code generation dictionary file path that you want to create is invalid.");
                            errors.Add("Please change the filename in settings --> file locations tab");
                            errorfree = false;


                        }
                        else
                        {

                            errors.Add("\t [ " + Config.ThreadTempFilepaths[z - 1] + " ] ");

                            errorfree = false;
                        }
                    }

                    if (z == 0)
                    {
                        if ((Config.testConfigfilepaths()).Where((v, index) => (index > 0) && v == false).Any())
                        {
                            errors.Add("Invalid temporary file paths specified with detail below:");
                            errors.Add("Please change the temporary file paths in settings --> Temp File Locations tab");
                            errors.Add("List of affected temporary codegen files below:");
                        }
                    }

                    z++;
                }

                if (!errorfree)
                {
                    return errorfree;
                }
            }

            filelist = "";
            filecollisions.Clear();


            foreach (var path in Config.ThreadTempFilepaths)
            {

                if (File.Exists(path))
                {
                    filecollisions.Add(path);
                }

            }
            if (filecollisions.Count() > 0)
            {
                
                bool everytwo = false;
                foreach(var f in filecollisions.Select(x=> x+ (everytwo ? "\r\n":"\t"))){
                    filelist +=f;
                    everytwo = (everytwo ? false : true);
                }
               var a = System.Windows.MessageBox.Show("There are exisiting code generator temp files, \r\nthat will interfere with the code generation list below:\r\n\r\n"+filelist +"\r\n\r\nDo you want me to delete them?","Delete Old Temp Files?",MessageBoxButton.OKCancel);
               if (a == MessageBoxResult.OK)
               {
                   bool exceptionoccured = false;
                   var exception = new Exception();
                   foreach (var pa in filecollisions)
                   {
                       try
                       {
                           File.Delete(pa);
                       }
                       catch (Exception e)
                       {
                           exceptionoccured = true;
                           exception = e;
                           break;
                       }
                   }
                   if (exceptionoccured)
                   {
                       throw exception;
                   }
               }
               else
               {
                   errors.Add("There are exisiting temporary files, possibly from a prevoius code generation task sitting in the selected directory.");
                   errors.Add("The following files below need to be deleted or moved /");
                   errors.Add("or another directory selected from the settings --> file locations tab all together");
                   errors.Add("You may want to use the Temp File Locations tab to select a directory for the affected files below:");
                   errors.Add("");
                   foreach (var pa in filecollisions)
                   {
                       errors.Add(pa);
                       
                   }
                   errors.Add("");
                   errorfree = false;

               }
            }

            return errorfree;
        }

        private void setpercentage(object sender, WPFcontrols.SelectionChangedEventArgs e)
        {
            e.Handled = true;
            var a = (sender as WPFcontrols.TabControl);
            bool match = false;
            foreach (WPFcontrols.TabItem i in a.Items)
            {
                if (((string)i.Header) == "Processor Usage" && i.IsSelected)
                {
                    match = true;
                }

            }
            if (match)
            {
                Percentageforprocess.Dispatcher.BeginInvoke(new Action(() => Percentageforprocess.Visibility = System.Windows.Visibility.Visible));


            }
            else
            {
                Percentageforprocess.Dispatcher.BeginInvoke(new Action(() => Percentageforprocess.Visibility = System.Windows.Visibility.Hidden));
            }
        }

        private void Radio_Automatic_Checked(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            //weird error where the designer has attached the event before the controll is fully instanciated
            if (CustomTempFileGrid != null)
            {
                CustomTempFileGrid.Visibility = System.Windows.Visibility.Hidden;
                TempFileCleanupRadio.IsChecked = true;

                Config.iscustomtempfile = false;
            }
            
        }

        private void Radio_Custom_Checked(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            CustomTempFileGrid.Visibility = System.Windows.Visibility.Visible;
            Config.iscustomtempfile = true;
        }

        private void SettingsTabControl_selectionChanged(object sender, WPFcontrols.SelectionChangedEventArgs e)
        {
            e.Handled = true;
            var a = (sender as WPFcontrols.TabControl);
            //something is wrong with this wpf event it should only be against the inner tab control
            if (a.Name == "SettingsTabControl")  
            {
                foreach (WPFcontrols.TabItem i in a.Items)
                {
                    if (((string)i.Header) == "Select Characture Set" && i.IsSelected)
                    {
                        SetupCharsetTab();
                    }

                    if (((string)i.Header) == "Concurrent Processing" && i.IsSelected)
                    {
                        SetupConcurrentProcessingTab();
                    }

                    if (((string)i.Header) == "Temp File Locations" && i.IsSelected)
                    {
                        SetupConcurrentProcessingTab();

                        if (AutomaticTempFileConfig.IsChecked == null ? false : AutomaticTempFileConfig.IsChecked.Value)
                        {
                            setupAutoTempFilepaths();
                        }
                        else
                        {
                            setupCustomFilePaths();

                        }
                    }
                    if (((string)i.Header) == "Save / Load Settings" && i.IsSelected)
                    {
                        SettingsViewTbox.Text = Config.SettingsListforView();
                    }
                }
            }
        }

        private void TempThreadListBox_SelectionChanged(object sender, WPFcontrols.SelectionChangedEventArgs e)
        {
            e.Handled = true;
            
                setTempfileselectCount(TempThreadListBox.SelectedItems.Count);
            
        }

        private void setTempfileselectCount(int p)
        {
            SelectedTMPFileslbl.Content = "Selected Temp Files: " + p.ToString();
            if (p > 0)
            {
                Set_temp_DirectoryBUTTON.IsEnabled = true;
            }
            else
            {

                Set_temp_DirectoryBUTTON.IsEnabled = false;
            }
        }

        private void AssignTempDirectory(object sender, RoutedEventArgs e)
        {
            List<string> selectedpaths = new List<string>();
            foreach (WPFcontrols.Label item in TempThreadListBox.SelectedItems)
            {
                selectedpaths.Add((string)item.Content);
            }
            List<string> updatedpaths = new List<string>();

            var fb = new System.Windows.Forms.FolderBrowserDialog();
            System.Windows.Forms.DialogResult r = fb.ShowDialog();

            if (r == System.Windows.Forms.DialogResult.OK)
            {
                if (!string.IsNullOrEmpty(fb.SelectedPath))
                {
                    foreach (var path in selectedpaths)
                    {
                        var finf = new FileInfo(path);
                        var fname = "";
                        if (System.IO.Path.GetPathRoot(finf.DirectoryName) == finf.DirectoryName)
                        {
                            fname = (finf.FullName).Replace(finf.DirectoryName, "");
                        }
                        else
                        {
                           fname  = (finf.FullName).Replace(finf.DirectoryName + "\\", "");
                        }
                        if (System.IO.Path.GetPathRoot(fb.SelectedPath) == fb.SelectedPath)
                        {
                            updatedpaths.Add(fb.SelectedPath + fname);
                        }
                        else
                        {
                            updatedpaths.Add(fb.SelectedPath + "\\" + fname);
                        }
                    }
                    


                }

                foreach (string updatedpath in updatedpaths)
                {
                    var finf = new FileInfo(updatedpath);
                    var fname="";
                    if (System.IO.Path.GetPathRoot(finf.DirectoryName) == finf.DirectoryName)
                    {
                        fname = (finf.FullName).Replace(finf.DirectoryName, "");
                    }else{
                    fname = (finf.FullName).Replace(finf.DirectoryName + "\\", "");
                    }
                    Config.ThreadTempFilepaths[getindexofcollectionOFstring(ref Config.ThreadTempFilepaths, fname)] = updatedpath;
                }

                TempThreadListBox.Items.Clear();
                for (int l = 0; l < Config.NumberofThreadsSelected; l++)
                {
                    WPFcontrols.Label v = new WPFcontrols.Label();
                    v.Content = Config.ThreadTempFilepaths[l];
                    TempThreadListBox.Items.Add(v);

                   

                }

            }
        }

        private int getindexofcollectionOFstring(ref List<string> list, string fname)
        {
           return Config.ThreadTempFilepaths.IndexOf(Config.ThreadTempFilepaths.Where(x => x.Contains(fname)).FirstOrDefault());
        }



        public void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs args)
        {
            try
            {
                shutdownAllthreadTasks();

            }
            catch
            {

            }
            Exception e = (Exception)args.ExceptionObject;
            System.Windows.MessageBox.Show("Exception caught by the Gobal Exception handler, Details: (below)\r\n\r\n" + e.Message + "\r\n\r\nINNER EXCEPTION IF PRESENT (details below)\r\n\r\n" + (e.InnerException == null ? "" : e.InnerException.Message));
        }

        private void shutdownAllthreadTasks()
        {
            if (ThreadTasks != null)
            {
               
                    for (int x = 0; x < ThreadTasks.Count(); x++)
                    {
                        if (ThreadTasks[x] != null)
                        {
                            if (Utility.Utility.GetThreadContextMenuetext(ThreadTasks[x].ConfigCodeHeader, ThreadTasks[x].notification, ThreadState(ThreadTasks[x])) == "Shut Down Code Generation Process")
                            {
                                ThreadTasks[x].ShutdownThread();
                            }
                        }

                    }
                                
            }
        }

        private void StardardCHARSETRadioCHECKED(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
           
            resetcharsetswhenbacktocustom();
            CustomCharsetGrid.Visibility = Visibility.Visible;
        }

        private void resetcharsetswhenbacktocustom()
        {
            CHKNUMS.IsChecked = true;
            CHKUPPER.IsChecked= true;
            CHKLOWER.IsChecked = true;
            if (CharsetpickerControl != null)
            {
                CharsetpickerControl.clearselections();

                CharsetpickerControl.setnumbersSelected();
                Config.StandardCharsetincludes[0] = true;
                CharsetpickerControl.setUPPERSSelected();
                Config.StandardCharsetincludes[1] = true;
                CharsetpickerControl.setLOWERSSelected();
                Config.StandardCharsetincludes[2] = true;
            }
        }

        private void CUSTOMCHARSETRadioCHECKED(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            
            CustomCharsetGrid.Visibility = System.Windows.Visibility.Hidden;
        }

        private void StandarcharsetChoice(object sender, RoutedEventArgs e)
        {
            if (CharsetpickerControl != null)
            {
                e.Handled = true;
                bool numbers = CHKNUMS.IsChecked.HasValue ? CHKNUMS.IsChecked.Value : false;
                bool uppers = CHKUPPER.IsChecked.HasValue ? CHKUPPER.IsChecked.Value : false;
                bool lowers = CHKLOWER.IsChecked.HasValue ? CHKLOWER.IsChecked.Value : false;
               
                CharsetpickerControl.clearselections();
                if (numbers)
                {
                    CharsetpickerControl.setnumbersSelected();
                    
                    
                }
                else
                {
                   
                }
                if (uppers)
                {

                    CharsetpickerControl.setUPPERSSelected();
                    
                }
                else
                {
                   
                }
                if (lowers)
                {

                    CharsetpickerControl.setLOWERSSelected();
                   
                }
                else
                {
                  
                }


            }
        }

        private void Radio_TempFileCleanChecked(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            Config.cleanuptempfiles = true;
        }

        private void Radio_TempFileAsISChecked(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            Config.cleanuptempfiles = false;


        }

        private void SaveCFG(object sender, RoutedEventArgs e)
        {
            var sfd = new Microsoft.Win32.SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = ext;
            sfd.Filter = Utility.Utility.CodegenConfigSFDfilter;
            sfd.FilterIndex = 1;
            
            bool? resultofdialog = sfd.ShowDialog();
            if (resultofdialog.HasValue ? resultofdialog.Value : false)
            {
                try
                {
                    var savefilename = sfd.FileName;
                    Stream stream = File.Open(savefilename, FileMode.Create);
                    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter BF = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                    BF.Serialize(stream, Config);
                    stream.Dispose();
                }
                catch
                {

                    WPFMBOX.Show("An error occured while trying to the save the configuration.");
                }



              

            }
            else
            {

            }
                
        }

        private void LoadCFG(object sender, RoutedEventArgs e)
        {
            var ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.AddExtension = true;
            ofd.DefaultExt = ext;
            ofd.Filter = Utility.Utility.CodegenConfigSFDfilter;
            ofd.FilterIndex = 1;
            
            bool? resultofdialog = ofd.ShowDialog();
            if (resultofdialog.HasValue ? resultofdialog.Value : false)
            {
                Configuration cfg = new Configuration();
                try
                {
                    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter BF = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                    Stream stream = File.OpenRead(ofd.FileName);

                    cfg = (Configuration)BF.Deserialize(stream);

                    WPFMBOX.Show("Config file validation complete it will now be applied.");
                }
                catch
                {
                    WPFMBOX.Show("There was an error trying to load this configuration.");

                }

                ApplyConfiguration(ref cfg);
            }
        }

        private void ApplyConfiguration(ref Configuration cfg)
        {
            this.Config.MaxCodeSize = cfg.MaxCodeSize;
            Config.MinCodeSize = cfg.MinCodeSize;
            StandardCharsetRadio.IsChecked = true;
            
            CHKNUMS.IsChecked = cfg.StandardCharsetincludes[0];
            CHKUPPER.IsChecked = cfg.StandardCharsetincludes[1];
            CHKLOWER.IsChecked = cfg.StandardCharsetincludes[2];
            Config.StandardCharsetincludes = cfg.StandardCharsetincludes;

            Config.charactureset = cfg.charactureset;
            Config.Filepath = cfg.Filepath;
            Config.ThreadTempFilepaths = cfg.ThreadTempFilepaths;
            TempFilesASisRadio.IsChecked = (!cfg.cleanuptempfiles);
            TempFileCleanupRadio.IsChecked = cfg.cleanuptempfiles;

            CustomCharsetRadio.IsChecked = (!cfg.isStandardcharset);
            if (cfg.isStandardcharset)
            {
                bool numbers = CHKNUMS.IsChecked.HasValue ? CHKNUMS.IsChecked.Value : false;
                bool uppers = CHKUPPER.IsChecked.HasValue ? CHKUPPER.IsChecked.Value : false;
                bool lowers = CHKLOWER.IsChecked.HasValue ? CHKLOWER.IsChecked.Value : false;

                CharsetpickerControl.clearselections();
                if (numbers)
                {
                    CharsetpickerControl.setnumbersSelected();


                }
                else
                {

                }
                if (uppers)
                {

                    CharsetpickerControl.setUPPERSSelected();

                }
                else
                {

                }
                if (lowers)
                {

                    CharsetpickerControl.setLOWERSSelected();

                }
                else
                {

                }

            }

            Config.isStandardcharset = cfg.isStandardcharset;
            CharsetpickerControl.CharacterSetCTRL.setselectedchars(cfg.charactureset);

            

            CustomTempFileConfig.IsChecked = cfg.iscustomtempfile;
            AutomaticTempFileConfig.IsChecked = (!cfg.iscustomtempfile);
                        
            
            MainFileLocationLBL.Content = "FILE PATH SET: " + Config.Filepath;
            if (AutomaticTempFileConfig.IsChecked == null ? false : AutomaticTempFileConfig.IsChecked.Value)
            {
                setupAutoTempFilepaths();
            }
            else
            {
                setupCustomFilePaths();

            }

            Setcodegencharacturesets();
            SetupConcurrentProcessingTab();
            numbofthredsSlider.Value = cfg.NumberofThreadsSelected;
            SettingsViewTbox.Text = Config.SettingsListforView();
            

        }

        private void FinishprocessCloseorCancel(object sender, RoutedEventArgs e)
        {
            if ((string)((sender as WPFcontrols.Button).Content) == "Close")
            {
                FinishButton.Content = "Cancel";
                FinishprocessCanvas.Visibility = Visibility.Hidden;
                ProcessCompleteLBL.Content = "Congratulations Process\r\nComplete";
                FinishProcessA();
            }
            else
            {
            tokensource.Cancel();

            }
        }

      
    }
}
